Skip to content

Conversation

@JaapvanEkris
Copy link
Owner

New functionality in 0.9.7

  • Addition of the 'Calories' workout type. You can now program Intervals and splits based on calories to be burned
  • Introduction of splits in the fit-file. The fit-file now also has splits, which makes the fit-file closer to a native Garmin recording of the same session

Bugfixes and robustness improvements in 0.9.7

  • Improvement of the Moving Least Squares regressor:
    • Code refactoring to isolate this function from Flywheel.js, allowing a more thorough testing of its behaviour
    • Introduced the 'Local Goodness of Fit' function to improve the robustness against noise. This reduces the effect of outliers on stroke detection, the Force curve, Power curve and Handle speed curve
    • Introduction of a 'Gaussian Weight' filter to reduce the effects of flanks on the regression in a specific datapoint
    • Added documentation about the mathematical foundations of the algorithms used
  • Upgrade of the flywheel position pre-filter, which now can handle systematic errors of flywheel positioning. This is more effective at reducing measurement noise and allows a reduction of the code complexity in Flyhweel.js as all dependent algorithms can use the same datastream again.
  • Fixed a bug in the initialisation of the Flywheel.js
  • Improved logging in the Strava uploader for better troubleshooting (see issue 145)
  • Increased the test coverage of key algorithms

@Abasz
Copy link
Collaborator

Abasz commented Jan 12, 2026

Kayak first test data is incorrect. It include the stroke number as a delta time.

please use this file:
KayakFirst_Blue_4x500m.csv

if (x === undefined || isNaN(x) || y === undefined || isNaN(y)) { return }

// Ensure weight is valid and positive
const _weight = (w === undefined || isNaN(w) || w <= 0) ? 1 : w
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you disallowing zero weight element? But most importantly why are you making a zero weight element to have full weight?

If weight is invalid I think we should either skip the addition or feed zero in (which is essentially the same as not adding anything).

In this case if we have a zero GoF because for some reason the fit is so bad or there is another error (not sure if this is possible in reality but still) then we would add this value with full weight. that contradicts the logic in my view.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you disallowing zero weight element? But most importantly why are you making a zero weight element to have full weight?

In normal behaviour, an absolute 0 weight will not happen. In essence, when you find a zero some weight is not filled in (essentially a bug in calling the function). So defaulting to 1 essentially moves it to OLS mode.

In this case if we have a zero GoF because for some reason the fit is so bad or there is another error (not sure if this is possible in reality but still) then we would add this value with full weight. that contradicts the logic in my view.

A GoF of 0 typically arises from some error condition in the application, most likely to be systematic. So falling back to OLS instead of ignoring a whole datastream seemed the wisest approach here.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In normal behaviour, an absolute 0 weight will not happen.

Yes I agree, it just occurred to me that from an interface, component behaviour perspective this is not the best since it makes assumption on the caller side (that it pre-handles zero weight). What I mean is that a caller typically expects a zero weight to be disregarded yet, it gets included with full weight. Also this is not the behaviour of the other weighted series, if zero weight is passed to them they will gladly include the zero (which essentially excludes the from the calculation). So this is why I raised this.

A GoF of 0 typically arises from some error condition in the application, most likely to be systematic. So falling back to OLS instead of ignoring a whole datastream seemed the wisest approach here.

I have not tested so I suppose this is a justification :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants